package cn.codeforfun.ws;

import cn.codeforfun.config.GetHttpSessionConfigurator;
import cn.codeforfun.util.JSONUtil;
import cn.codeforfun.util.UserService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Package cn.codeforfun.ws
 * Project cloud-websocket
 * Author WangBin
 * Email bin.wang12@pactera.com
 * Created on 2017/8/14 0014 10:33
 * version 1.0.0
 */
@Service
@ServerEndpoint(value = "/chatSocket", configurator = GetHttpSessionConfigurator.class)
public class WSChatService {

  private static int                                onlineCount = 0;//在线人数
  private static ConcurrentHashMap<String, Session> publicMap   = new ConcurrentHashMap();
  private static ConcurrentHashMap<String, Session> privateMap  = new ConcurrentHashMap();
  private final  Logger                             log         = Logger.getLogger(getClass());
  @Resource
  private UserService userService;

  public static synchronized int getOnlineCount() {
    return onlineCount;
  }

  public static synchronized void addOnlineCount() {
    WSChatService.onlineCount++;
  }

  public static synchronized void subOnlineCount() {
    if (onlineCount <= 0) return;
    WSChatService.onlineCount--;
  }

  @OnOpen
  public void onOpen(Session session, EndpointConfig config) {
    HttpSession session1 = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
    Object      userName = session1.getAttribute("user");
    if (userName != null) {
      String name = (String) userName;
      privateMap.put(name, session);
    }
    publicMap.put(session.getId(), session);
    addOnlineCount();
  }

  @OnClose
  public void onClose(Session session) {
    Principal userPrincipal = session.getUserPrincipal();
    if (userPrincipal != null) {
      privateMap.remove(userPrincipal.getName());
    }
    publicMap.remove(session.getId());
    subOnlineCount();
  }

  @OnError
  public void onError(Session session, Throwable throwable) {
    if (throwable == null) return;
    if (!(throwable instanceof IOException)) {
      log.error(throwable);
    }
  }

  @OnMessage
  public void onMessage(String message, Session session) {
    log.info("\r\n接受到消息===" + message);
  }

  /**
   * 私聊
   *
   * @param message  消息
   * @param userName 用户名
   */
  public void sendMessage(String message, String userName) {
    Map map = new HashMap();
    map.put("name", userService.getCurrentUser());
    map.put("content", message);
    if (privateMap.containsKey(userName))
      privateMap.get(userName).getAsyncRemote().sendText(JSONUtil.toJson(map));
  }

  public void sendMessage(Map map) {
    if (StringUtils.isEmpty(map.get("content"))) return;
    String content = (String) map.get("content");
    if (StringUtils.isEmpty(map.get("toUser"))) {
      this.sendMessage(content);
    } else {
      String userName = (String) map.get("toUser");
      this.sendMessage(content, userName);
    }
  }

  /**
   * 广播
   *
   * @param message 消息
   */
  public void sendMessage(String message) {
    Map map = new HashMap();
    map.put("name", userService.getCurrentUser());
    map.put("content", message);
    Set<Map.Entry<String, Session>> entries = publicMap.entrySet();
    entries.forEach(entry -> entry.getValue().getAsyncRemote().sendText(JSONUtil.toJson(map)));
  }
}
